package com.wrx.club_management_backend.utils;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

/* Redis缓存工具 */
@Component
public class RedisCacheWorker {

    @Autowired
    StringRedisTemplate stringRedisTemplate;


    /**
     * 缓存穿透问题
     * @param id 查询对象的id
     * @param prefix 缓存前缀
     * @param expireTime 过期时间
     * @param unit 时间单位
     * @param type 缓存对象的类型
     * @param dbFallback 如果未命中，应执行的getById函数
     * @return 要查询的对象
     * @param <ID> id的类型
     * @param <R> 返回对象的类型
     */
    public <ID, R> R queryWithPassThrough(
            ID id,
            String prefix,
            Long expireTime,
            TimeUnit unit,
            Class<R> type,
            Function<ID, R> dbFallback
    ) {

        R r = null;
        String key = prefix + id;
        String json = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(json)) { // 如果不是空串
            r = JSONUtil.toBean(json, type);
            return r;
        }
        // 如果是空串的话，直接返回null
        if ("".equals(json)) return null;

        // 如果缓存未命中，直接执行dbFallback
        r = dbFallback.apply(id);

        if (r == null) {
            stringRedisTemplate.opsForValue().set(key, "", expireTime, TimeUnit.MINUTES);
        } else {
            //4. 缓存真正数据
            stringRedisTemplate.opsForValue().set(
                    key,                                     // CacheKey
                    JSONUtil.toJsonStr(r),                   // 缓存对象的JSON串
                    expireTime,                              // 过期时间
                    unit                                     // 时间单位
            );
        }
        return r;
    }

}
